#!/usr/bin/python
from __future__ import division
import visual, visual.controls
from idee_utils import *
from idee_controls import *

import lockdict, archdesc, sys, random, os

def drawaxis(extents):
  for i in range(1, 10):
    visual.curve(pos=[(i/10, 1, 0), (i/10, 1, 1.05)], color=(0.25, 0.25, 0.25))
    visual.curve(pos=[(i/10, -0.05, 0), (i/10, 1, 0)], color=(0.25, 0.25, 0.25))

    visual.curve(pos=[(1, i/10, 0), (1, i/10, 1.05)], color=(0.25, 0.25, 0.25))
    visual.curve(pos=[(-0.05, i/10, 0), (1, i/10, 0)], color=(0.25, 0.25, 0.25))

    visual.curve(pos=[(1, -0.05, i/10), (1, 1, i/10)], color=(0.25, 0.25, 0.25))
    visual.curve(pos=[(-0.05, 1, i/10), (1, 1, i/10)], color=(0.25, 0.25, 0.25))

  visual.curve(pos=[(0, 0, 0), (1, 0, 0)])
  visual.curve(pos=[(0, 0, 0), (0, 1, 0)])
  visual.curve(pos=[(0, 1, 0), (0, 1, 1)])

  visual.curve(pos=[(0, 1, 0), (1, 1, 0)])
  visual.curve(pos=[(1, 0, 0), (1, 1, 0)])
  visual.curve(pos=[(0, 1, 1), (1, 1, 1)])

  visual.curve(pos=[(1, 0, 1), (1, 1, 1)])
  visual.curve(pos=[(1, 1, 0), (1, 1, 1)])
  visual.curve(pos=[(1, 0, 0), (1, 0, 1)])

  visual.curve(pos=[(0, 0, 1), (1, 0, 1)])
  visual.curve(pos=[(0, 0, 1), (0, 1, 1)])
  visual.curve(pos=[(0, 0, 1), (0, 0, 0)])

  visual.label(pos=(-0.1, -0.1, 0), text='(0, 0, ' + str(extents[2]) + ')', box=0, line=0)
  visual.label(pos=(1, -0.1, 0), text='T = ' + str(extents[0]), box=0, line=0)
  visual.label(pos=(-0.1, 1, 0), text='A = ' + str(extents[1]), box=0, line=0)
  visual.label(pos=(0, 1, 1.1), text='E = 0', box=0, line=0)

def simpoint(a):
  global newresults

  a.evaluate(results)
  awaitresults.append(a)

def wavepoint(a):
  global newresults

  a.evaluate(results, lxt='sim.lxt')
  awaitresults.append(a)

def drawcontrols():
  # Important: 1:1 mapping of pixels to coordinates
  c = visual.controls.controls(range=320, width=460, height=640)
  a = archdescui(c.display, (-225, 285))
  b = visual.controls.button(pos=(180, -205), text='Simulate', width=90, height=50, action=lambda: simpoint(a.get()))
  b = visual.controls.button(pos=(180, -145), text='Wave', width=90, height=50, action=lambda: wavepoint(a.get()))
  return (c, a)

def addarchs(PP2, PA2):
  global PP, PA

  PP.extend(PP2)
  PA.extend(PA2)
  PA = select(PA, unique(PP))
  PP = select(PP, unique(PP))

def drawpareto((PP2, PA2), boxes=False, lines=False, all=False, color=[0]):
  if not all:
    PI = getpareto(PP2, (extents[0], extents[1], -extents[2]))
    PP2 = select(PP2, PI)
    PA2 = select(PA2, PI)
  
  cl = pointcolors[color[0]]
  color[0] = color[0] + 1

  for p in PP2:
    x = p[0]/extents[0]
    y = p[1]/extents[1]
    z = 1+p[2]/extents[2]
    #cl = pointcolor

    if boxes:
      BA.append(visual.box(pos=(x+(1-x)/2, y+(1-y)/2, z/2), length=1-x, height=1-y, width=z, color=cl))
      #cl = boxpointcolor

    if lines:
      #BA.append(visual.box(pos=(x+(1-x)/2, y+(1-y)/2, z/2), length=1-x, height=1-y, width=z, color=(0, 0, 1)))
      visual.curve(pos=[(x, y, z), (1, y, z)], color=cl, radius=0.001)
      visual.curve(pos=[(x, y, z), (x, 1, z)], color=cl, radius=0.001)
      visual.curve(pos=[(x, y, z), (x, y, 0)], color=cl, radius=0.001)
      
    visual.sphere(pos=(p[0]/extents[0], p[1]/extents[1], 1+p[2]/extents[2]), radius = 0.01, color=cl)

  addarchs(PP2, PA2)

def mainloop():
  prevobj = None
  prevcolor = None
  lastobj = None
  selectlabel = visual.label(pos=(0, 0, 0), text='', visible=0, box=0, xoffset=25, yoffset=25, linecolor=selectcolor)
  selectbox = visual.box(visible=0, color=(1.0, 0.75, 0.75))

  while 1:
    visual.rate(100)

    c.interact()  
    if scene.mouse.clicked:
      scene.mouse.getclick()
      obj = scene.mouse.pick

      if obj and isinstance(obj, visual.sphere):
        if prevobj:
          prevobj.color = prevcolor
        if prevobj != obj:
          prevcolor = obj.color
        prevobj = obj
        obj.color = selectcolor
        
        for i in range(len(PP)):
          p = PP[i]
          a = PA[i]
      
          if obj.pos[0] == p[0]/extents[0] and obj.pos[1] == p[1]/extents[1] and obj.pos[2] == 1+p[2]/extents[2]:
            selectlabel.text = 'T = ' + str(p[0]) + '\nA = ' + str(p[1]) + '\nE = ' + str(p[2])
            selectlabel.pos = obj.pos
            selectlabel.visible = 1
            
            selectbox.pos = obj.pos
            selectbox.pos=(obj.pos[0]+(1-obj.pos[0])/2, obj.pos[1]+(1-obj.pos[1])/2, obj.pos[2]/2)
            selectbox.length=1-obj.pos[0]
            selectbox.height=1-obj.pos[1]
            selectbox.width=obj.pos[2]

            print '(' + str(p[0]) + ', ' + str(p[1]) + ', ' + str(p[2]) + ')'
            print str(a)
          
            ui.set(a)
      else:
        selectlabel.visible = 0
        
    if scene.kb.keys:
      k = scene.kb.getkey()
      if  k == 'q':
        return
      if k == 'b':
        selectbox.visible = 1 - selectbox.visible
      if k == 'c':
        for b in BA:
          b.visible = 1 - b.visible
  
    if awaitresults != []:
      results.lock()
      for a in awaitresults:
        if len(results[a]) == 1:
          if lastobj and lastobj.color == addedcolor:
            lastobj.color = oldaddedcolor
      
          r = results[a][0]
          PP.append([r[0], r[1], r[2]])
          PA.append(a)
    
          lastobj = visual.sphere(pos=tuple([r[0]/extents[0], r[1]/extents[1], 1+r[2]/extents[2]]), radius = 0.01, color = addedcolor)

          print 'Added ' + str(a) + ' at (' + str(r[0]) + ', ' + str(r[1]) + ', ' + str(r[2]) + ')'
          
          try:
            os.rename('sim.lxt', 'idee.lxt')
            os.system('gtkwave idee.lxt all.save &')
          except:
            pass
        
          awaitresults.remove(a)
      results.unlock()  

scene = visual.display(title='Interactive DSE exploration environment', width=460, height=460, pos=(0, 0))
scene.select()
scene.center = (1, 1, 0)
scene.forward = (1, 1, -1)
scene.up = (1, 1, 0)

extents = [0.1, 100, -0.1]
drawaxis(extents)

PP = []
PA = []
BA = []

results = lockdict.lockdict()
awaitresults = []

selectcolor   = (1, 0, 0)
addedcolor    = (0, 1, 0)
oldaddedcolor = (0, 1, 1)

pointcolors   = [(1, 1, 1), (0, 0, 1), (1, 1, 0), (1, 0, 1)]

#drawpareto(loadmatlab('robocup_brute_new_4.m'), True)
#drawpareto(loadmatlab('robocup_pisa_strange.m'))
#drawpareto(loadascii('alldompoints'), True)
#drawpareto(loadascii('noisepoints'), False)

#drawpareto(loadascii('robocup_pisa_limited_all.ascii'), True)
#drawpareto(loadmatlab('robocup_pisa_limited_50pop_9.m'), True)
#drawpareto(loadascii('robocup_brute_limited.ascii'),True)
#drawpareto(loadascii('robocup_brute_limited.ascii'), False, True)

a = 1
boxes = True
lines = all = False

while a < len(sys.argv):
  if sys.argv[a] == 'all':
    all = True
  elif sys.argv[a] == 'noall':
    all = False
  elif sys.argv[a] == 'lines':
    lines = True
  elif sys.argv[a] == 'nolines':
    lines = False
  elif sys.argv[a] == 'boxes':
    boxes = True
  elif sys.argv[a] == 'noboxes':
    boxes = False
  else:
    if sys.argv[a][-1] == 'm':
      drawpareto(loadmatlab(sys.argv[a]), boxes, lines, all)
    else:
      drawpareto(loadascii(sys.argv[a]), boxes, lines, all)

    boxes = True
    lines = all = False

  a = a + 1

(c, ui) = drawcontrols()

mainloop()
